package com.regulareport.common.utils.parser;

import com.googlecode.aviator.AviatorEvaluator;
import com.regulareport.common.constant.ReportVerifyConstants;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author
 * @create 2025-10-21
 */
public class VerifyFormulaParser {

    public static void main(String[] args) {
        VerifyFormulaParser parser = new VerifyFormulaParser();

        System.out.println("=== 公式解析器 ===");
        System.out.println("支持的运算符: " + String.join(", ", ReportVerifyConstants.OPERATOR_ARR));
        System.out.println();

//        String[] exampleFormulas = {
//                "a + b * c",
//                "x >= y && z != 0",
//                "price * quantity + tax",
//                "GF3333_10._C=GF3333_10.1_C+GF3333_10.2_C+GF3333_10.3_C+GF3333_10.4_C+GF3333_10.5_C+GF3333_10.7_C"
////                ,
////                "count++ && total--",
////                "name == \"John\" && age > 18",
////                "(a + b) * (c - d) / 2.5"
//        };
//
//        System.out.println("示例公式解析:");
//        System.out.println("==========================");
//        for (String formula : exampleFormulas) {
//            System.out.println("\n原始公式: " + formula);
//            List<String> elements = VerifyFormulaParser.parseFormula(formula);
//            System.out.println(parser.formatElements(elements));
//        }
        Map valueMap = new HashMap();
        valueMap.put("GF3333_10._C", 10);
        valueMap.put("GF3333_10.1_C", 0);
        valueMap.put("GF3333_10.2_C", 1);
        valueMap.put("GF3333_10.3_C", 2);
        valueMap.put("GF3333_10.4_C", 3);
        valueMap.put("GF3333_10.5_C", 4);
        valueMap.put("GF3333_10.7_C", 5);

        Object result = AviatorEvaluator.execute("GF3333_10._C == GF3333_10.1_C + GF3333_10.2_C + GF3333_10.3_C + GF3333_10.4_C + GF3333_10.5_C + GF3333_10.7_C", valueMap);

        System.out.println("\n" + "------------------------------------");

    }

    public static List<String> parseFormula(String formula, String[] matchStrs) {
        List<String> tokens = new ArrayList<>();
        if (formula == null || formula.trim().isEmpty()) {
            return tokens;
        }
//        StringBuilder currentToken = new StringBuilder();
        // 构建运算符正则表达式模式
        String operatorPattern = buildOperatorPattern(matchStrs);
        Pattern pattern = Pattern.compile(operatorPattern);
        Matcher matcher = pattern.matcher(formula);

        int lastIndex = 0;
        while (matcher.find()) {
            // 添加运算符前的普通文本
            if (matcher.start() > lastIndex) {
                String beforeOperator = formula.substring(lastIndex, matcher.start());
                if (!beforeOperator.trim().isEmpty()) {
                    tokens.add(beforeOperator.trim());
                }
            }

            // 添加运算符本身
//            String operator = matcher.group();
//            tokens.add(operator);

            lastIndex = matcher.end();
        }

        // 添加最后一个运算符后的文本
        if (lastIndex < formula.length()) {
            String remaining = formula.substring(lastIndex);
            if (!remaining.trim().isEmpty()) {
                tokens.add(remaining.trim());
            }
        }

        return tokens;
    }

    private static String buildOperatorPattern(String[] matchStrs) {
        // 按长度降序排序，避免短运算符误匹配
        String[] sortedOperators = Arrays.copyOf(matchStrs, matchStrs.length);
        Arrays.sort(sortedOperators, (a, b) -> Integer.compare(b.length(), a.length()));

        StringBuilder patternBuilder = new StringBuilder();
        patternBuilder.append("(");

        for (int i = 0; i < sortedOperators.length; i++) {
            if (i > 0) {
                patternBuilder.append("|");
            }
            // 转义特殊字符
            patternBuilder.append(Pattern.quote(sortedOperators[i]));
        }

        patternBuilder.append(")");
        return patternBuilder.toString();
    }

    private static void classifyTokens(List<String> tokens) {
        Set<String> operators = new HashSet<>(Arrays.asList(ReportVerifyConstants.OPERATOR_ARR));

        for (String token : tokens) {
            String classification = classifyToken(token, operators);
            System.out.println("  " + token + " -> " + classification);
        }
    }

    private static String classifyToken(String token, Set<String> operators) {
        if (operators.contains(token)) {
            return "运算符";
        } else if (isNumber(token)) {
            return "数字";
        } else if (isVariable(token)) {
            return "变量";
        } else if (isStringLiteral(token)) {
            return "字符串字面量";
        } else if (isParenthesis(token)) {
            return "括号";
        } else {
            return "未知类型";
        }
    }

    private static boolean isNumber(String str) {
        return str.matches("-?\\d+(\\.\\d+)?");
    }

    private static boolean isVariable(String str) {
        return str.matches("[a-zA-Z_][a-zA-Z0-9_]*");
    }

    private static boolean isStringLiteral(String str) {
        return str.startsWith("\"") && str.endsWith("\"");
    }

    private static boolean isParenthesis(String str) {
        return str.equals("(") || str.equals(")") || str.equals("[") ||
                str.equals("]") || str.equals("{") || str.equals("}");
    }


    public String formatElements(List<String> elements) {
        StringBuilder sb = new StringBuilder();
        sb.append("公式元素解析结果:\n");
        sb.append("===========================").append("\n");

        for (String element : elements) {
            sb.append("$").append(element);
        }

        return sb.toString();
    }
}
